/**
 * Apache License Version 2.0, January 2004 http://www.apache.org/licenses/
 * <p>
 * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 * <p>
 * 1. Definitions.
 * <p>
 * "License" shall mean the terms and conditions for use, reproduction, and distribution as defined
 * by Sections 1 through 9 of this document.
 * <p>
 * "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is
 * granting the License.
 * <p>
 * "Legal Entity" shall mean the union of the acting entity and all other entities that control, are
 * controlled by, or are under common control with that entity. For the purposes of this definition,
 * "control" means (i) the power, direct or indirect, to cause the direction or management of such
 * entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
 * outstanding shares, or (iii) beneficial ownership of such entity.
 * <p>
 * "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this
 * License.
 * <p>
 * "Source" form shall mean the preferred form for making modifications, including but not limited
 * to software source code, documentation source, and configuration files.
 * <p>
 * "Object" form shall mean any form resulting from mechanical transformation or translation of a
 * Source form, including but not limited to compiled object code, generated documentation, and
 * conversions to other media types.
 * <p>
 * "Work" shall mean the work of authorship, whether in Source or Object form, made available under
 * the License, as indicated by a copyright notice that is included in or attached to the work (an
 * example is provided in the Appendix below).
 * <p>
 * "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or
 * derived from) the Work and for which the editorial revisions, annotations, elaborations, or other
 * modifications represent, as a whole, an original work of authorship. For the purposes of this
 * License, Derivative Works shall not include works that remain separable from, or merely link (or
 * bind by name) to the interfaces of, the Work and Derivative Works thereof.
 * <p>
 * "Contribution" shall mean any work of authorship, including the original version of the Work and
 * any modifications or additions to that Work or Derivative Works thereof, that is intentionally
 * submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or
 * Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this
 * definition, "submitted" means any form of electronic, verbal, or written communication sent to
 * the Licensor or its representatives, including but not limited to communication on electronic
 * mailing lists, source code control systems, and issue tracking systems that are managed by, or on
 * behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding
 * communication that is conspicuously marked or otherwise designated in writing by the copyright
 * owner as "Not a Contribution."
 * <p>
 * "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a
 * Contribution has been received by Licensor and subsequently incorporated within the Work.
 * <p>
 * 2. Grant of Copyright License. Subject to the terms and conditions of this License, each
 * Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
 * irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display,
 * publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or
 * Object form.
 * <p>
 * 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor
 * hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 * (except as stated in this section) patent license to make, have made, use, offer to sell, sell,
 * import, and otherwise transfer the Work, where such license applies only to those patent claims
 * licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or
 * by combination of their Contribution(s) with the Work to which such Contribution(s) was
 * submitted. If You institute patent litigation against any entity (including a cross-claim or
 * counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work
 * constitutes direct or contributory patent infringement, then any patent licenses granted to You
 * under this License for that Work shall terminate as of the date such litigation is filed.
 * <p>
 * 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works
 * thereof in any medium, with or without modifications, and in Source or Object form, provided that
 * You meet the following conditions:
 * <p>
 * (a) You must give any other recipients of the Work or Derivative Works a copy of this License;
 * and
 * <p>
 * (b) You must cause any modified files to carry prominent notices stating that You changed the
 * files; and
 * <p>
 * (c) You must retain, in the Source form of any Derivative Works that You distribute, all
 * copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding
 * those notices that do not pertain to any part of the Derivative Works; and
 * <p>
 * (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative
 * Works that You distribute must include a readable copy of the attribution notices contained
 * within such NOTICE file, excluding those notices that do not pertain to any part of the
 * Derivative Works, in at least one of the following places: within a NOTICE text file distributed
 * as part of the Derivative Works; within the Source form or documentation, if provided along with
 * the Derivative Works; or, within a display generated by the Derivative Works, if and wherever
 * such third-party notices normally appear. The contents of the NOTICE file are for informational
 * purposes only and do not modify the License. You may add Your own attribution notices within
 * Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the
 * Work, provided that such additional attribution notices cannot be construed as modifying the
 * License.
 * <p>
 * You may add Your own copyright statement to Your modifications and may provide additional or
 * different license terms and conditions for use, reproduction, or distribution of Your
 * modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and
 * distribution of the Work otherwise complies with the conditions stated in this License.
 * <p>
 * 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution
 * intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms
 * and conditions of this License, without any additional terms or conditions. Notwithstanding the
 * above, nothing herein shall supersede or modify the terms of any separate license agreement you
 * may have executed with Licensor regarding such Contributions.
 * <p>
 * 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service
 * marks, or product names of the Licensor, except as required for reasonable and customary use in
 * describing the origin of the Work and reproducing the content of the NOTICE file.
 * <p>
 * 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor
 * provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation,
 * any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 * PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or
 * redistributing the Work and assume any risks associated with Your exercise of permissions under
 * this License.
 * <p>
 * 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including
 * negligence), contract, or otherwise, unless required by applicable law (such as deliberate and
 * grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for
 * damages, including any direct, indirect, special, incidental, or consequential damages of any
 * character arising as a result of this License or out of the use or inability to use the Work
 * (including but not limited to damages for loss of goodwill, work stoppage, computer failure or
 * malfunction, or any and all other commercial damages or losses), even if such Contributor has
 * been advised of the possibility of such damages.
 * <p>
 * 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works
 * thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty,
 * indemnity, or other liability obligations and/or rights consistent with this License. However, in
 * accepting such obligations, You may act only on Your own behalf and on Your sole responsibility,
 * not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each
 * Contributor harmless for any liability incurred by, or claims asserted against, such Contributor
 * by reason of your accepting any such warranty or additional liability.
 * <p>
 * END OF TERMS AND CONDITIONS
 * <p>
 * APPENDIX: How to apply the Apache License to your work.
 * <p>
 * To apply the Apache License to your work, attach the following boilerplate notice, with the
 * fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include
 * the brackets!)  The text should be enclosed in the appropriate comment syntax for the file
 * format. We also recommend that a file or class name and description of purpose be included on the
 * same "printed page" as the copyright notice for easier identification within third-party
 * archives.
 * <p>
 * Copyright 2016 Alibaba Group
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.benmu.framework.extend.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.benmu.framework.R;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.benmu.framework.utils.BMHookGlide;
import com.benmu.framework.utils.ImageUtil;
import com.benmu.framework.utils.WXCommonUtil;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.adapter.IWXImgLoaderAdapter;
import com.taobao.weex.common.WXImageStrategy;
import com.taobao.weex.dom.ImmutableDomObject;
import com.taobao.weex.dom.WXImageQuality;
import com.taobao.weex.ui.component.WXImage;
import com.taobao.weex.ui.view.WXImageView;

import java.security.MessageDigest;

public class DefaultWXImageAdapter implements IWXImgLoaderAdapter {
    private static final String PLACEHOLDER_DEFAULT = "default";
    private Bitmap mErrorBitmap;

    public DefaultWXImageAdapter() {
    }


    private boolean validatePlaceHolder(WXImageStrategy strategy) {
        return true;
    }

    @Override
    public void setImage(String url, final ImageView view,
                         WXImageQuality quality, final WXImageStrategy strategy) {
        if (view == null || !(view instanceof WXImageView)) return;
        Log.d("url>>>>>>", "url>>>>>" + url);
        WXImageView wxImageView = (WXImageView) view;
        wxImageView.setImageBitmap(null);
        if (TextUtils.isEmpty(url)) {
            handleError((WXImageView) view);
            if (strategy != null && strategy.getImageListener() != null) {
                strategy.getImageListener().onImageFinish(url, view, true, null);
            }
            return;
        }
        wxImageView.setCurrentUrl(url);
        if (url.indexOf(".svg") != -1) {
            GlideApp.with(WXEnvironment.getApplication())
                    .as(PictureDrawable.class)
                    .error(R.drawable.place_holder)
                    .listener(new SvgSoftwareLayerSetter())
                    .apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
                    .load(BMHookGlide.handleResource(url))
                    .into(wxImageView);
        } else {
            BMHookGlide.load(WXEnvironment.getApplication(), url)
                    .apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
                    .into(new BMDesignSimpleTarget
                            (wxImageView, strategy, validatePlaceHolder
                                    (strategy), url));
        }
    }

    private Bitmap getErrorBitmap(Context context) {
        if (mErrorBitmap == null) {
            mErrorBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.place_holder);
        }
        return mErrorBitmap;
    }

    private void handleError(WXImageView imageView) {
        WXImage component = imageView.getComponent();
        if (component == null) return;
        ImmutableDomObject domObject = component.getDomObject();
        if (domObject == null) return;
        Bitmap bitmap = getErrorBitmap(imageView.getContext());
        if (domObject.getLayoutWidth() > 0 && domObject.getLayoutHeight() > 0) {
            int target = Math.min((int) (domObject.getLayoutWidth()), (int) (domObject
                    .getLayoutHeight())) / 2;
            Bitmap zoomBitmap = ImageUtil.zoomImage(bitmap, target, target);
            if (zoomBitmap != null) {
                imageView.drawErrorBitmap(zoomBitmap);
            }
        }
    }


    private class BMDesignSimpleTarget extends SimpleTarget<Drawable> {
        private WXImageView mView;
        private WXImageStrategy mStrategy;
        private boolean mPlaceHolder;
        private String mUrl;

        private BMDesignSimpleTarget(WXImageView wxImageView, WXImageStrategy strategy, boolean
                placeHolder, String url) {
            this.mView = wxImageView;
            this.mStrategy = strategy;
            this.mPlaceHolder = placeHolder;
            this.mUrl = url;
        }

        @Override
        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
            if (denyPreviousRequest(mUrl, mView)) return;
            mView.hideLoading();
            mView.hideErrorBitmap();

            if (resource instanceof GifDrawable) {
                //加载图片为动图
                showAndCropGif(mUrl, mView, mStrategy);
            } else if (resource instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) resource;
                mView.setImageBitmap(bitmapDrawable.getBitmap());

                if (mStrategy != null && mStrategy.getImageListener() != null) {
                    mStrategy.getImageListener().onImageFinish(mUrl, mView, true, null);
                }
            } else {
                Log.e("ImageAdapter", "无法处理的图片类型");
                if (mStrategy != null && mStrategy.getImageListener() != null) {
                    mStrategy.getImageListener().onImageFinish(mUrl, mView, true, null);
                }
            }
        }

        @Override
        public void onLoadStarted(Drawable placeholder) {
            super.onLoadStarted(placeholder);
            int[] wh = WXCommonUtil.getComponentWH(mView.getComponent());
            Log.d("onLoadStarted", " mStrategy.placeHolder -> " + mStrategy.placeHolder);
            if (PLACEHOLDER_DEFAULT.equals(mStrategy.placeHolder)) {
                mView.showLoading(wh[0], wh[1]);
            }
            mView.hideErrorBitmap();
        }

        @Override
        public void onLoadFailed(@Nullable Drawable errorDrawable) {
            super.onLoadFailed(errorDrawable);
            if (denyPreviousRequest(mUrl, mView)) return;
            mView.hideLoading();
            handleError((WXImageView) mView);
            if (mStrategy != null && mStrategy.getImageListener() != null) {
                mStrategy.getImageListener().onImageFinish(mUrl, mView, true, null);
            }
        }
    }


    private boolean denyPreviousRequest(String url, View imageView) {
        return !url.equals(((WXImageView) imageView).getCurrentUrl());
    }


    private void showAndCropGif(String url, WXImageView view, WXImageStrategy mStrategy) {
        BMRadiusTransfer radiusTransfer = new BMRadiusTransfer(WXEnvironment.getApplication(), view);
        BitmapPool bitmapPool = Glide.get(WXEnvironment.getApplication()).getBitmapPool();
        BMHookGlide.load(WXEnvironment.getApplication(), url)
                .apply(new RequestOptions().transform(radiusTransfer))
                .into(view);

        if (mStrategy != null && mStrategy.getImageListener() != null) {
            mStrategy.getImageListener().onImageFinish(url, view, true, null);
        }
    }

    private static class BMRadiusTransfer extends BitmapTransformation {

        private WXImageView mView;

        public BMRadiusTransfer(Context context) {
            this(context, null);
        }

        BMRadiusTransfer(Context context, WXImageView imageView) {
            super(context);
            this.mView = imageView;
        }

        @Override
        public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
            this.updateDiskCacheKey(messageDigest);
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int
                outHeight) {
            return roundCrop(pool, toTransform);
        }

        private Bitmap roundCrop(BitmapPool pool, Bitmap source) {

            if (source == null || mView == null) return source;

            Drawable roundDrawable = mView.getRoundDrawable(source);
            return roundDrawable == null ? source : ImageUtil.drawableToBitmap(roundDrawable);
        }
    }
}
